#!/usr/bin/python
#coding:utf-8
'''
cv2使用模型
2020-07-01
'''

import os,time
import cv2
import numpy as np 

#读支持中文
# img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), -1)
#写支持中文
# cv2.imencode('.jpg', carnum[2])[1].tofile(jpgFil)


def showImg(path,local):
    '''
    显示原图和模型框
    args:
        path：图片地址
        local:模型图位置，(xmin,ymin,xmax,ymax)
    '''
    # 不支持中文路径
    # img = cv2.imread(path)
    #支持中文路径
    img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), -1)

    #画框
    cv2.rectangle(img, (int(local[0]), int(local[1])), (int(local[2]), int(local[3])), (0,0,255), 2)  #(x,y),(x+w,y+h)

    cv2.namedWindow("model",cv2.WINDOW_NORMAL) #使用图片大小显示
    # cv2.resizeWindow("model", 640, 480)  #重置图片大小
    cv2.imshow("model",img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def saveFile(path,local,modelPath):
    '''
    剪裁指定区域图片并报错
    args:
        path:图片地址
        local:模型图位置,(xmin,ymin,xmax,ymax)
        modelPath:模型图保存地址
    '''
    img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), -1)
    #xmin,ymin,xmax,ymax
    modelImg=img[int(local[1]):int(local[3]),int(local[0]):int(local[2])] #ymin:ymax,xmin:xmax

    # cv2.namedWindow("model",cv2.WINDOW_NORMAL)
    cv2.imshow('model', modelImg)

    #中文路径保存图片
    # cv2.imencode('.jpg', modelImg)[1].tofile(modelPath) 
    
    #非中文保存图片
    # cv2.imwrite(modelPath, modelImg)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def find(img,modelImg):
    '''
    识别身份证在图片中位置
    '''
    if cv2.__version__ !="3.4.2":
        print("cv2建议使用3.4.2.16版本")

    try:
        ##加载灰度模型图
        img1 = cv2.UMat(cv2.imdecode(np.fromfile(modelImg, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)) # queryImage in Gray
        if np.all(img1.get()) == None:
            print(modelImg,"加载异常")
            return
        img1 = img_resize(img1, 640)

        # self.showimg(img1)
        #img1 = idocr.hist_equal(img1)

        #加载灰度待识别图
        img2 = cv2.UMat(cv2.imdecode(np.fromfile(img, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)) # trainImage in Gray
        if np.all(img2.get())==None:
            print(img,"加载异常")
            return

        # print(img2.get().shape)
        img2 = img_resize(img2, 1920)

        #加载原图
        #img2 = idocr.hist_equal(img2)
        # img_org = cv2.UMat(cv2.imread(img))
        img_org = cv2.UMat(cv2.imdecode(np.fromfile(img, dtype=np.uint8), -1)) # trainImage in Gray
        img_org = img_resize(img_org, 1920)

        #  Initiate SIFT detector
        t1 = round(time.time() * 1000)

        sift = cv2.xfeatures2d.SIFT_create()
        # find the keypoints and descriptors with SIFT
        kp1, des1 = sift.detectAndCompute(img1,None)
        kp2, des2 = sift.detectAndCompute(img2,None)

        FLANN_INDEX_KDTREE = 0
        index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
        search_params = dict(checks = 10)

        flann = cv2.FlannBasedMatcher(index_params, search_params)
        matches = flann.knnMatch(des1,des2,k=2)

        # store all the good matches as per Lowe's ratio test.
        #两个最佳匹配之间距离需要大于ratio 0.7,距离过于相似可能是噪声点
        good = []
        for m,n in matches:
            if m.distance < 0.7*n.distance:
                good.append(m)

        #reshape为(x,y)数组
        MIN_MATCH_COUNT = 10
        if len(good)>MIN_MATCH_COUNT:
            src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
            dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)

            #用HomoGraphy计算图像与图像之间映射关系, M为转换矩阵
            M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
            # matchesMask = mask.ravel().tolist()

            if np.all(M) ==None:
                return None

            M_r=np.linalg.inv(M)

            h,w = cv2.UMat.get(img1).shape
            im_r = cv2.warpPerspective(img_org, M_r, (w,h))
            # showimg(im_r)
            
        else:
            print("Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT))
            im_r=None
            # matchesMask = None

        #draw_params = dict(matchColor = (0,255,0), # draw matches in green color
        #           singlePointColor = None,
        #           matchesMask = matchesMask, # draw only inliers
        #           flags = 2)
        #img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
        # plt.imshow(img3, 'gray'),plt.show()
        t2 = round(time.time() * 1000)

        print(u'查找身份证耗时:%s' % (t2 - t1))
        return im_r
    except BaseException as e:
        import traceback
        traceback.print_exc()
        return None

def img_resize(crop, dwidth):
    '''
    重置图片大小
    args:
        core图片
        dwidth:图片宽度
    '''
    
    return crop 

    size = crop.get().shape
    height = size[0]
    width = size[1]
    height = height * dwidth / width
    crop = cv2.resize(src=crop, dsize=(dwidth, int(height)), interpolation=cv2.INTER_CUBIC)
    return crop

def showimg(img):
    cv2.namedWindow("contours", 0);
    cv2.startWindowThread() #加在这个位置
    cv2.resizeWindow("contours", 1280, 720)
    cv2.imshow("contours", img)
    key=cv2.waitKey(0)
    cv2.destroyAllWindows()
